In C++, managing container growth is an architectural dance between Size (current elements) and Capacity (reserved memory). For contiguous containers like vector and string, reaching capacity triggers a reallocation: the system finds a larger memory block, moves all elements, and destroys the old block. This is a costly $O(n)$ operation that causes iterator invalidation—your pointers to old elements become "dangling" and dangerous.
1. Expansion Strategy
To avoid frequent reallocations, vector implementations allocate "buffer" space. The c.reserve(n) command explicitly sets a minimum capacity without adding elements, while c.shrink_to_fit() is a non-binding request to return excess memory to the OS.
2. The Resize vs. Reserve Distinction
While reserve only affects the buffer, resize(n) actively changes the container's logic. Shrinking via resize destroys elements, while expanding adds default-initialized values.
resize shrinks the container, iterators to deleted elements are invalidated. If expansion causes reallocation, ALL iterators are invalidated.